#include "NfcApiBridgePlugin.h"	// CNfcApiBridgePlugin
#include "NfcApiBridgePlugin.pan"	  	// panic codes

#include <utf.h> 
#include <HttpRequest.h>
#include <QueryParser.h>
#include <EscapeUtils.h>

#define RETURN_WITH_400_IF_EMPTY(str, response) if(!(str).Length()) { (response).SendErrorL(400); return; }
#define RETURN_WITH_500_IF_ERROR(err, response) if(err < 0) { (response).SendErrorL(500); return; }

_LIT8(KSuccess, "1");

//  Member Functions

CNfcApiBridgePlugin* CNfcApiBridgePlugin::NewLC()
{
    CNfcApiBridgePlugin* self = new (ELeave) CNfcApiBridgePlugin;
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
}

CNfcApiBridgePlugin* CNfcApiBridgePlugin::NewL()
{
    CNfcApiBridgePlugin* self = CNfcApiBridgePlugin::NewLC();
    CleanupStack::Pop(self);
    return self;
}

CNfcApiBridgePlugin::CNfcApiBridgePlugin()
{
}

void CNfcApiBridgePlugin::ConstructL()
{
    User::LeaveIfError(iSession.Connect());
#ifdef LOGGING
    User::LeaveIfError(iFs.Connect());
    CREATE_LOG_INSTANCE(iFs, _L("E:\\NfcPluginLog.txt"));
    LOG1(_L("Created plugin instance"));
#endif // LOGGING
}

CNfcApiBridgePlugin::~CNfcApiBridgePlugin()
{
    iSession.Close();
#ifdef LOGGING
    LOG1(_L("Deleting plugin instance"));
    DELETE_LOG_INSTANCE();
    iFs.Close();
#endif // LOGGING
}

void CNfcApiBridgePlugin::ServiceL(MHttpRequest* aReq)
{
    LOG1(_L("--> ServiceL"));
    
    TRAPD(err, DoServiceL(aReq));
    if (err != KErrNone)
        {
        LOG2(_L("DoServiceL() leaved with %d"), err);
        TRAP(err, aReq->GetResponse()->SendErrorL(500));
        if (err != KErrNone)
            {
            LOG2(_L("SendErrorL() leaved with %d"), err);
            // Could not complete even error.
            // Nothing we can do.
            }
        }
    LOG1(_L("<-- ServiceL"));
}

void CNfcApiBridgePlugin::DoServiceL(MHttpRequest* aReq)
{
    _LIT8(KMethod, "method");
    _LIT8(KWidgetId, "widgetId");
    
    _LIT8(KReadTag, "readTag");
    _LIT8(KSetForeground, "setForeground");
    
    _LIT8(KSendMessage, "sendMessage");
    _LIT8(KSetResponse, "setResponse");
    _LIT8(KTransactionLog, "transactionLog");
    
    RQueryParser parser;
    parser.ParseL( aReq->GetRequest()->GetQuery() );
    
    TPtrC8 method = parser.GetValue(KMethod);
    RETURN_WITH_400_IF_EMPTY(method, *aReq->GetResponse());
    
    TPtrC8 widgetId = parser.GetValue(KWidgetId);
    RETURN_WITH_400_IF_EMPTY(method, *aReq->GetResponse());
    
    if(method == KReadTag)
        ReadTagL(*aReq->GetResponse(), parser, widgetId);
    else if(method == KSetForeground)
        SetForegroundL(*aReq->GetResponse(), parser, widgetId);
    else if(method == KSendMessage)
    	SendMessageL(*aReq->GetResponse(), parser, widgetId);
    else if(method == KSetResponse)
    	SetResponseL(*aReq->GetResponse(), parser, widgetId);
    else if(method == KTransactionLog)
    	TransactionLogL(*aReq->GetResponse(), parser, widgetId);
    else
        aReq->GetResponse()->SendErrorL(400);
    
    parser.Close();
}

void CNfcApiBridgePlugin::ReadTagL(MHttpServletResponse & aResponse, RQueryParser & aParser, TDesC8 const & aWidgetId)
    {
    _LIT8(KTnf, "tnf");
    _LIT8(KType, "type");
    _LIT8(KTimeout, "timeout");
    
    TPtrC8 tnf = aParser.GetValue(KTnf);
    RETURN_WITH_400_IF_EMPTY(tnf, aResponse);
    
    TPtrC8 type = aParser.GetValue(KType);
    RETURN_WITH_400_IF_EMPTY(type, aResponse);
    
    TPtrC8 timeoutStr = aParser.GetValue(KTimeout);
    RETURN_WITH_400_IF_EMPTY(timeoutStr, aResponse);
    TInt timeout;
    TLex8 timeoutLex(timeoutStr);
    User::LeaveIfError(timeoutLex.Val(timeout));
    
    LOG5(_L8("ReadTagL(%S, %S, %S, %d)"), &aWidgetId, &tnf, &type, timeout);
    
    HBufC8 * tagContents = iSession.ReadTagL(aWidgetId, tnf, type, timeout);
    CleanupDeletePushL(tagContents);
    aResponse.SetStatus(200);
    aResponse.SendL(*tagContents);
    CleanupStack::PopAndDestroy(tagContents);
    }

void CNfcApiBridgePlugin::SetForegroundL(MHttpServletResponse & aResponse, RQueryParser & aParser, TDesC8 const & aWidgetId)
    {
    _LIT8(KOnForeground, "onForeground");
    _LIT8(KTrue, "true");
    
    TPtrC8 onForegroundStr = aParser.GetValue(KOnForeground);
    RETURN_WITH_400_IF_EMPTY(onForegroundStr, aResponse);
    TBool onForeground = (onForegroundStr == KTrue);
    
    LOG3(_L8("SetForegroundL(%S, %d)"), &aWidgetId, onForeground);
    iSession.SetForegroundL(aWidgetId, onForeground);
    aResponse.SetStatus(200);
    aResponse.SendL(KSuccess);
    }

void CNfcApiBridgePlugin::SendMessageL(MHttpServletResponse & aResponse, RQueryParser & aParser, TDesC8 const & aWidgetId)
	{
    _LIT8(KMessageId, "messageId");
    _LIT8(KContent, "content");
	
    TPtrC8 messageId = aParser.GetValue(KMessageId);
    RETURN_WITH_400_IF_EMPTY(messageId, aResponse);
    TPtrC8 content = aParser.GetValue(KContent);
    RETURN_WITH_400_IF_EMPTY(content, aResponse);

    LOG4(_L8("SendMessageL(\"%S\", \"%S\", \"%S\")"), &aWidgetId, &messageId, &content);
    TInt response = iSession.SendMessageL(aWidgetId, messageId, content, 600 );
    aResponse.SetStatus(200);
    aResponse.SendL(KSuccess);
	}

void CNfcApiBridgePlugin::SetResponseL(MHttpServletResponse & aResponse, RQueryParser & aParser, TDesC8 const & aWidgetId)
	{
    _LIT8(KMessageId, "messageId");
    _LIT8(KContent, "content");
	
    TPtrC8 messageId = aParser.GetValue(KMessageId);
    RETURN_WITH_400_IF_EMPTY(messageId, aResponse);
    TPtrC8 content = aParser.GetValue(KContent);
    RETURN_WITH_400_IF_EMPTY(content, aResponse);

    LOG4(_L8("SetResponseL(\"%S\", \"%S\", \"%S\")"), &aWidgetId, &messageId, &content);
    TInt response = iSession.SetResponseL(aWidgetId, messageId, content, 600 );
    aResponse.SetStatus(200);
    aResponse.SendL(KSuccess);
	}

void CNfcApiBridgePlugin::TransactionLogL(MHttpServletResponse & aResponse, RQueryParser & aParser, TDesC8 const & aWidgetId)
	{
    LOG2(_L8("TransactionLogL(\"%S\")"), &aWidgetId);
    HBufC8* response = iSession.TransactionLogL(aWidgetId);
    CleanupStack::PushL(response);
    aResponse.SetStatus(200);
    aResponse.SendL(*response);
    CleanupStack::PopAndDestroy(response);
	}


